package cn.charlab.boot.oss;

import cn.charlab.boot.exception.OsException;
import cn.charlab.boot.oss.properties.OssProperties;
import cn.charlab.boot.template.StorageTemplate;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.VoidResult;
import org.apache.commons.io.IOUtils;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

public class OssTemplate implements StorageTemplate {

    private OssProperties ossProperties;

    private OSS ossClient;

    public OssTemplate(OssProperties ossProperties) {
        this.ossProperties = ossProperties;
    }

    @Override
    public boolean createBucket(String bucket) throws OsException {
        if (StringUtils.hasLength(bucket)) {
            return false;
        }
        if (bucketExists(bucket)) {
            return false;
        }
        try {

            ossClient.createBucket(bucket);
            return true;
        } catch (Exception e) {
            throw new OsException(e);
        }
    }

    @Override
    public boolean deleteBucket(String bucket) throws OsException {
        VoidResult result = ossClient.deleteBucket(bucket);
        return result.getResponse().getStatusCode() == 200;
    }

    @Override
    public boolean bucketExists(String bucket) throws OsException {
        return ossClient.doesBucketExist(bucket);
    }

    @Override
    public void putObject(String bucket, String key, InputStream input) throws OsException {
        putObject(bucket,key,input,null);
    }

    @Override
    public void putObject(String bucket, String key, InputStream input, Map<String, Object> headers) throws OsException {
        ObjectMetadata metadata = new ObjectMetadata();
       if (headers != null){
           headers.forEach((k,v)->metadata.setHeader(k,v));
       }
        ossClient.putObject(bucket,key,input,null);
    }

    @Override
    public InputStream getObject(String bucket, String key) throws OsException {
        OSSObject ossObject = ossClient.getObject(bucket,key);
        return ossObject.getObjectContent();
    }

    @Override
    public void getObject(String bucket, String key, OutputStream out) throws OsException {
        OSSObject ossObject = ossClient.getObject(bucket,key);
        try (InputStream in = ossObject.getObjectContent()) {
            IOUtils.copyLarge(in, out);
        } catch (Exception e) {
            throw new OsException(e);
        }
    }

    @Override
    public boolean deleteObject(String bucket, String key) throws OsException {
        VoidResult result = ossClient.deleteObject(bucket,key);
        return result.getResponse().getStatusCode() == 200;
    }

    @Override
    public boolean existObject(String bucket, String key) throws OsException {
        return ossClient.doesObjectExist(bucket,key);
    }

    @Override
    public void destroy() throws Exception {
        ossClient.shutdown();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        init();
    }


    private void init() {
        if (!s3Enable()){
            return;
        }
        CredentialsProvider credentialProvider = CredentialsProviderFactory
                .newDefaultCredentialProvider(ossProperties.getAccessKey(),ossProperties.getSecretKey());
         ossClient = new OSSClientBuilder().build(ossProperties.getEndPoint(), credentialProvider);
    }


    private boolean s3Enable(){
        if (ossProperties == null || !StringUtils.hasLength(ossProperties.getEndPoint())){
            return false;
        }
        return true;
    }


}
